package cn.buk.qms.service;

import cn.buk.tms.dao.*;
import cn.buk.tms.entity.bill.BillInfo;
import cn.buk.tms.entity.order.flight.FlightChangeOrder;
import cn.buk.tms.entity.order.flight.FlightOrder;
import cn.buk.tms.entity.order.flight.FlightRefundOrder;
import cn.buk.tms.entity.order.hotel.HotelOrder;
import cn.buk.tms.entity.order.train.TrainOrder;
import cn.buk.tms.entity.order.train.TrainRefundOrder;
import cn.buk.tms.entity.order.vas.VasOrder;
import cn.buk.tms.hotel.dao.HotelOrderDao;
import cn.buk.tms.train.dao.TrainOrderDao;
import cn.buk.tms.train.dao.TrainRefundOrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

import static cn.buk.tms.common.constant.TmsOrderConstant.*;

@Service
public class BillAutoTaskServiceImpl implements BillAutoTaskService {

  private final FlightOrderDao flightOrderDao;
  private final FlightRefundOrderDao refundOrderDao;
  private final FlightChangeOrderDao changeOrderDao;

  private final VasOrderDao vasOrderDao;
  private final HotelOrderDao hotelOrderDao;
  private final TrainOrderDao trainOrderDao;
  private final TrainRefundOrderDao trainRefundOrderDao;

  private final BillDao billDao;

  @Autowired
  public BillAutoTaskServiceImpl(FlightOrderDao flightOrderDao,
                                 FlightRefundOrderDao refundOrderDao,
                                 FlightChangeOrderDao changeOrderDao,
                                 VasOrderDao vasOrderDao,
                                 HotelOrderDao hotelOrderDao,
                                 TrainOrderDao trainOrderDao,
                                 TrainRefundOrderDao trainRefundOrderDao,
                                 BillDao billDao) {
    this.flightOrderDao = flightOrderDao;
    this.refundOrderDao = refundOrderDao;
    this.changeOrderDao = changeOrderDao;
    this.vasOrderDao = vasOrderDao;
    this.hotelOrderDao = hotelOrderDao;
    this.trainOrderDao = trainOrderDao;
    this.trainRefundOrderDao = trainRefundOrderDao;
    this.billDao = billDao;
  }

  /**
   * 系统定时同步 账单销账状态到机票订单
   */
  @Override
  public void autoSyncBillPaid2FlightOrder(final String agentName, final int max) {
    List<FlightOrder> flightOrders = flightOrderDao.searchUnpaidFlightOrders(max);

    for (FlightOrder o : flightOrders) {
      List<BillInfo> billInfos = billDao.searchBillInfos(o.getEnterpriseId(), o.getOrderNo(), BILL_TYPE_FLIGHT);
      if (billInfos.isEmpty()) {
        continue;
      }

      //机票账单可以做分离操作，因此只有所有相关的账单都销账了，此订单才能更新为已销账状态
      int paidCount = 0;
      String billNos = null;
      for(BillInfo billInfo: billInfos) {
        if (BillInfo.CUSTOMER_PAYMENT_RECEIVED.equalsIgnoreCase(billInfo.getBePaid())) {
          paidCount++;
          billNos = billNos == null ? billInfo.getBillNum(): billNos + ", " + billInfo.getBillNum();
        }
      }
      if (paidCount == billInfos.size()) {
        // 已销账
        flightOrderDao.setFlightOrderWriteOff(o.getEnterpriseId(), agentName, o.getId(), "同步账单(" + billNos + ")付款状态");
      }
    }
  }

  /**
   * 同步 账单销账状态到退票单
   */
  @Override
  public void autoSyncBillPaid2RefundOrder(final String agentName, final int max) {
    List<FlightRefundOrder> orders = refundOrderDao.searchUnpaidOrders(max);

    for (FlightRefundOrder o : orders) {
      List<BillInfo> billInfos = billDao.searchBillInfos(o.getEnterpriseId(), o.getRefundOrderNo(), BILL_TYPE_FLIGHT_REFUND);
      if (billInfos.size() != 1) {
        continue;
      }

      BillInfo billInfo = billInfos.get(0);
      if (BillInfo.CUSTOMER_PAYMENT_RECEIVED.equalsIgnoreCase(billInfo.getBePaid())) {
        // 已销账
        refundOrderDao.setOrderWrittenOff(o.getEnterpriseId(), agentName, o.getId(), "同步账单(" + billInfo.getBillNum() + ")付款状态");
      }
    }
  }

  /**
   * 同步 账单销账状态到改签单
   */
  @Override
  public void autoSyncBillPaid2ChangeOrder(final String agentName, int max) {
    List<FlightChangeOrder> orders = changeOrderDao.searchUnpaidOrders(max);

    for (FlightChangeOrder o : orders) {
      List<BillInfo> billInfos = billDao.searchBillInfos(o.getEnterpriseId(), o.getChangeOrderNo(), BILL_TYPE_FLIGHT_CHANGE);
      if (billInfos.size() != 1) {
        continue;
      }

      BillInfo billInfo = billInfos.get(0);
      if (BillInfo.CUSTOMER_PAYMENT_RECEIVED.equalsIgnoreCase(billInfo.getBePaid())) {
        // 已销账
        changeOrderDao.setOrderWrittenOff(o.getEnterpriseId(), agentName, o.getId(), "同步账单(" + billInfo.getBillNum() + ")付款状态");
      }
    }
  }

  /**
   * 系统定时同步 账单销账状态到服务单
   */
  @Override
  public void autoSyncBillPaid2VasOrder(final String agentName, int max) {
    List<VasOrder> orders = vasOrderDao.searchUnpaidOrders(max);

    for (VasOrder o : orders) {
      doSyncBillPaidStatus2OrderPaidStatus(o.getEnterpriseId(), agentName, o.getId(), o.getOrderNo(), BILL_TYPE_VAS, vasOrderDao);
    }
  }

  private void doSyncBillPaidStatus2OrderPaidStatus(int enterpriseId, String username, int orderId, String orderNo,
                                                    String billType, BaseAbstractDao dao) {
    List<BillInfo> billInfos = billDao.searchBillInfos(enterpriseId, orderNo, billType);
    if (billInfos.size() != 1) {
      return;
    }

    BillInfo billInfo = billInfos.get(0);
    if (BillInfo.CUSTOMER_PAYMENT_RECEIVED.equalsIgnoreCase(billInfo.getBePaid())) {
      // 已销账
      dao.setOrderWriteOff(enterpriseId, username, orderId, "同步账单(" + billInfo.getBillNum() + ")付款状态");
    }
  }

  @Override
  public void autoSyncBillPaid2HotelOrder(String agentName, int max) {
    List<HotelOrder> orders = hotelOrderDao.searchUnpaidOrders(max);

    for (HotelOrder o : orders) {
      doSyncBillPaidStatus2OrderPaidStatus(o.getEnterpriseId(), agentName, o.getId(), o.getOrderNo(), BILL_TYPE_HOTEL, hotelOrderDao);
    }
  }

  @Override
  public void autoSyncBillPaid2TrainOrder(String agentName, int max) {
    List<TrainOrder> orders = trainOrderDao.searchUnpaidOrders(max);

    for (TrainOrder o : orders) {
      doSyncBillPaidStatus2OrderPaidStatus(o.getEnterpriseId(), agentName, o.getId(), o.getOrderNo(), BILL_TYPE_TRAIN, trainOrderDao);
    }

    this.autoSyncBillPaid2TrainRefundOrder(agentName);
  }

  private void autoSyncBillPaid2TrainRefundOrder(String agentName) {
    final int max = 5000;
    List<TrainRefundOrder> orders = trainRefundOrderDao.searchUnpaidOrders(max);

    for (TrainRefundOrder o : orders) {
      doSyncBillPaidStatus2OrderPaidStatus(o.getEnterpriseId(), agentName, o.getId(), o.getOrderNo(), BILL_TYPE_TRAIN, trainRefundOrderDao);
    }
  }

}
